/* Copyright 2008 Bas van den Berg
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Table.h"
#include "Utils.h"
#include "StringBuilder.h"

#include <stdio.h>
#include <string.h>

using namespace std;
using namespace Chronos;

Table::Table(int columns_, Alignment::Align align) 
    : margin(2)
    , rows(0)
    , column(0)
    , columns(columns_)
    , alignment(align)
{
    memset(columnSizes, 0, sizeof(columnSizes));
}


void Table::setMargin(int m) {
    margin = m;
}


void Table::addCell(const string& value) {
    cells.push_back(value);

    int visibleLen = getVisibleLen(value.c_str());
    if (visibleLen > columnSizes[column]) columnSizes[column] = visibleLen;

    column++;
    if (column == 1) rows++;
    if (column == columns) column = 0;
}


void Table::addCell(int value) {
    string str = Utils::itoa(value);
    addCell(str);
}


void Table::write(StringBuilder& output) const {
    int col = 0;

    for (unsigned int cell=0; cell<cells.size(); ++cell) {
        int cellWidth = columnSizes[col];

        string str = cells[cell];
        int visibleSize = getVisibleLen(str.c_str());

        int leftmargin = 0;
        if (alignment == Alignment::Right) leftmargin = (cellWidth - visibleSize);
        else if (alignment == Alignment::Center) leftmargin = ((cellWidth - visibleSize) / 2);
        for (int i=0; i<leftmargin; i++) output << ' ';

        output << str;

        col++;
        if (col == columns || cell==(cells.size()-1)) {
            col = 0;
            output << '\n';
        } else {
            int rightmargin = 0;
            if (alignment == Alignment::Left) rightmargin = (cellWidth - visibleSize);
            else if (alignment == Alignment::Center) rightmargin = cellWidth - (leftmargin + visibleSize);
            for (int i=0; i<rightmargin+margin; i++) output << ' ';
        }
    }
}


int Table::getVisibleLen(const char* str) const {
    const char* ptr = str;
    int visibleLen = 0;
    while(*ptr != 0) {
        if (*ptr == '\033') {
            while(*ptr != 'm') ptr++;
            ptr++;
            continue;
        }
        visibleLen++; 
        ptr++;
    }
    return visibleLen;
}

